package com.vanke.devops.domain.domain.schedulejob.impl;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.vanke.devops.dal.dao.ScheduleJobMapper;
import com.vanke.devops.dal.model.ScheduleJob;
import com.vanke.devops.dal.model.type.ScheduleJobStatus;
import com.vanke.devops.domain.base.BaseServiceImpl;
import com.vanke.devops.domain.domain.schedulejob.IScheduleJobService;
import com.vanke.devops.domain.domain.schedulejob.dto.ScheduleJobDTO;
import com.vanke.devops.domain.domain.schedulejob.param.ScheduleJobParam;
import com.vanke.devops.domain.domain.schedulejob.utils.ScheduleUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表  服务实现类
 * </p>
 *
 * @author 陈景阳
 * @since 2018-06-08
 */
@Service
public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobMapper, ScheduleJob> implements IScheduleJobService {

    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void init(){
        List<ScheduleJob> scheduleJobList = baseMapper.selectList(new EntityWrapper<>());
        for(ScheduleJob scheduleJob : scheduleJobList){
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
            //如果不存在，则创建
            if(cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            }else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }


    @Override
    public Page<ScheduleJobDTO> page(Integer pageNo, Integer pageSize) {
        Page<ScheduleJobDTO> page = new Page<>(pageNo,pageSize);
        List<ScheduleJob> list = baseMapper.selectPage(page,new EntityWrapper<>());
        List<ScheduleJobDTO> result = list.stream().map(this::getScheduleJobDTO).collect(Collectors.toList());
        page.setRecords(result);
        return page;
    }

    @Override
    public ScheduleJobDTO add(ScheduleJobParam param) {
        ScheduleJob entity = this.getScheduleJob(param);
        entity.setStatus(ScheduleJobStatus.NORMAL.getValue());
        super.add(entity);
        ScheduleUtils.createScheduleJob(scheduler, entity);
        return this.getInfo(entity.getId());
    }

    @Override
    public ScheduleJobDTO getInfo(Integer id) {
        ScheduleJob entity = baseMapper.selectById(id);
        return this.getScheduleJobDTO(entity);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ScheduleJobDTO update(Integer id, ScheduleJobParam param) {
        ScheduleJob entity = this.getScheduleJob(param);
        entity.setId(id);
        ScheduleUtils.updateScheduleJob(scheduler, entity);
        baseMapper.updateById(entity);
        return this.getInfo(id);
    }

    @Override
    public void deleteBatch(Integer[] jobIds) {
        for(Integer jobId : jobIds){
            ScheduleUtils.deleteScheduleJob(scheduler, jobId);
        }
        baseMapper.deleteBatchIds(Arrays.asList(jobIds));
    }

    @Override
    public int updateBatch(Integer[] jobIds, int status) {
        Map<String, Object> map = new HashMap<>();
        map.put("list", jobIds);
        map.put("status", status);
        return baseMapper.updateBatch(map);
    }

    @Override
    public void run(Integer[] jobIds) {
        for(Integer jobId : jobIds){
            ScheduleUtils.run(scheduler, baseMapper.selectById(jobId));
        }
    }

    @Override
    public void pause(Integer[] jobIds) {
        for(Integer jobId : jobIds){
            ScheduleUtils.pauseJob(scheduler, jobId);
        }

        updateBatch(jobIds, ScheduleJobStatus.PAUSE.getValue());
    }

    @Override
    public void resume(Integer[] jobIds) {
        for(Integer jobId : jobIds){
            ScheduleUtils.resumeJob(scheduler, jobId);
        }

        updateBatch(jobIds, ScheduleJobStatus.NORMAL.getValue());
    }

    private ScheduleJob getScheduleJob(ScheduleJobParam param){
        ScheduleJob entity = new ScheduleJob();
        entity.setBeanName(param.getBeanName());
        entity.setMethodName(param.getMethodName());
        entity.setCronExpression(param.getCronExpression());
        entity.setParams(param.getParams());
        entity.setRemark(param.getRemark());
        entity.setStatus(param.getStatus());
        return entity;
    }

    private ScheduleJobDTO getScheduleJobDTO(ScheduleJob entity){
        ScheduleJobDTO dto = new ScheduleJobDTO();
        dto.setBeanName(entity.getBeanName());
        dto.setCronExpression(entity.getCronExpression());
        dto.setMethodName(entity.getMethodName());
        dto.setParams(entity.getParams());
        dto.setStatus(entity.getStatus());
        dto.setRemark(entity.getRemark());
        dto.setId(entity.getId());
        return dto;
    }
}